﻿// Copyright (c) 2012 - 2020 Jared Zheng <jaredz at outlook dot com>
// Buddha Framework is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Create : 2012-12-01 version 0.1 Jared Zheng <jaredz at outlook dot com>
// Update : 2018-12-05 version 3.1.5 Jared Zheng <jaredz at outlook dot com>

#ifndef __AUTHOR_SERVER_IMP_H__
#define __AUTHOR_SERVER_IMP_H__

#pragma once

#include "commonpacket.h"
#include "CommonServer.h"
#include "CommonRoutine.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 授权网关服务器实现
class CAuthorServer : public ICommonServer, public CPAKHandler
{
public:
    CAuthorServer(void);
    virtual ~CAuthorServer(void);
    // CComponent
    // Command to set param value
    virtual UInt   Command(PCXStr pszCMD, uintptr_t utParam) OVERRIDE;
    virtual UInt   Update(void) OVERRIDE;

    virtual UInt   Init(CEventHandler& EventHandlerRef, CServerConfig& ConfigRef) OVERRIDE;
    virtual void   Exit(void) OVERRIDE;

    virtual bool   Start(void) OVERRIDE;
    virtual bool   Pause(bool bPause = true) OVERRIDE;
    virtual void   Stop(void) OVERRIDE;
    // CPAKHandler
    virtual bool   OnTcpDispatch(const PacketPtr& PktPtr, PTCP_PARAM pTcp) OVERRIDE;
    virtual bool   OnUdpDispatch(const PacketPtr& PktPtr, PUDP_PARAM pUdp) OVERRIDE;
    virtual bool   OnTcpAccept(Socket sAccept, Socket sListen) OVERRIDE;
    virtual bool   OnTcpConnect(UInt uError, Socket sConnect) OVERRIDE;
    virtual bool   OnTcpRecv(size_t stSize, PTCP_PARAM pTcp) OVERRIDE;//
    virtual bool   OnTcpSend(UInt uQueueLimit, Socket sSocket) OVERRIDE;//
    virtual bool   OnTcpClose(Socket sSocket, ULLong ullLiveData) OVERRIDE;

    virtual bool   OnUdpRecv(size_t stSize, PUDP_PARAM pUdp) OVERRIDE;//
    virtual bool   OnUdpSend(UInt uQueueLimit, Socket sSocket) OVERRIDE;//
    virtual bool   OnUdpClose(Socket sSocket, ULLong ullLiveData) OVERRIDE;
    // Routine
    virtual Socket_t          GetSocket(UInt uType) OVERRIDE;
    virtual PSERVER_INFO      GetServerInfo(UInt uType) OVERRIDE;
    virtual PSVR_COMMON_MAP   GetServerMap(UInt uType) OVERRIDE;
    virtual PRESULT_CHAIN     GetServerSort(UInt uType) OVERRIDE;
    virtual CServerConfig&    GetConfig(void) OVERRIDE;
    virtual CFileLog&         GetFileLog(void) OVERRIDE;
    virtual CEventHandlerPtr& GetMgrHandler(void) OVERRIDE;
    virtual CNetworkPtr&      GetNetworkPtr(void) OVERRIDE;
private:
    CAuthorServer(const CAuthorServer&);
    CAuthorServer& operator=(const CAuthorServer&);
    /// 配置相关
    bool  LoadConfig(void);
    void  UnloadConfig(void);

    bool  StartConnectCenterServer(void);
    bool  StartConnectAuthorDBServer(void);
    bool  StartListenMaster(void);
    bool  StartListenExternal(void);

    bool  CheckConnectCenterServer(void);
    bool  CheckConnectAuthorDBServer(void);
    bool  CheckListenMaster(void);
    bool  CheckListenExternal(void);

    void  StopConnectCenterServer(void);
    void  StopConnectAuthorDBServer(void);
    void  StopListenMaster(void);
    void  StopListenExternal(void);

    /// 向同步管理服务器注册/注销
    void  LinkCenterServer(void);
    void  UnlinkCenterServer(void);
    /// 向授权数据服务器注册/注销
    void  LinkAuthorDBServer(void);
    void  UnlinkAuthorDBServer(void);

    /// 处理同步管理服务器的信令包
    bool  DispatchCenterServer(const PacketPtr& PktPtr, PTCP_PARAM pTcp);
    /// 处理授权数据服务器的信令包
    bool  DispatchAuthorDBServer(const PacketPtr& PktPtr, PTCP_PARAM pTcp);
    /// 处理外网端的信令包
    bool  DispatchExternal(const PacketPtr& PktPtr, PTCP_PARAM pTcp);

    /// 同步服务器信息给控制台
    bool  SyncServerInfo(void);
    /// 同步业务管理服务器负载
    bool  SyncMasterSortInfo(CStream& Stream);

    bool  LoadExtConfig(void);
    bool  LoadExtRoutine(CKVNode& Root);
    bool  CreateRTTIObject(PCXStr pszObject, PCXStr pszName, PCXStr pszModule);
    bool  UnloadExtConfig(void);
    bool  UnloadExtRoutine(void);
private:
    Int                   m_nStatus;           ///< 服务器状态
    Int                   m_nCenterLink;       ///< 连接同步管理服务器状态
    Int                   m_nAuthorDBLink;     ///< 连接授权数据服务器状态
    // 框架例程开关, 由框架例程通过调用Command修改服务器实例对应参数
    Int                   m_nServerAck;        ///< 例程需要处理连接上服务器ACK信息PAKE_LINKACK/PAKE_UNLINKACK
    Int                   m_nSyncInfo;         ///< 例程需要处理服务器PAKE_LINK/PAKE_UPDATE同步信息时增加其他数据
    Int                   m_nCommonEvent;      ///< 例程需要处理服务器内部通用PAKE_COMMON_BEGIN/PAKE_COMMON_END事件
    //
    CServerConfig*        m_pConfig;           ///< 配置
    Socket                m_sConnectCenter;    ///< 内网, 连接同步管理服务器
    Socket                m_sConnectAuthorDB;  ///< 内网, 连接授权数据服务器
    Socket                m_sListenMaster;     ///< 内网, 监听业务管理服务器
    Socket                m_sListenExternal;   ///< 外网, 监听外网端
    CFileLog              m_FileLog;           ///< 简单文本日志
    CEventHandlerPtr      m_MgrHandler;        ///< 控制台回调接口
    CNetworkPtr           m_NetworkPtr;        ///< 网络
    CCommonRoutinePtr     m_RoutinePtr;        ///< 例程处理
    AUTHOR_ADDR           m_ServerInfo;        ///< 本服务器信息
    SERVER_INFO           m_MasterInfo;        ///< 业务管理服务器组统计数据
    RESULT_CHAIN          m_SortMaster;        ///< 业务管理服务器排序结果
    RESULT_CHAIN          m_SortUpdate;        ///< 更新业务管理服务器排序结果
    SVR_MASTER_MAP        m_Master;            ///< 业务管理服务器信息
};

INLINE CAuthorServer::CAuthorServer(void)
: m_nStatus(STATUSS_NONE)
, m_nCenterLink(STATUSL_NONE)
, m_nAuthorDBLink(STATUSL_NONE)
, m_nServerAck(TRUE)
, m_nSyncInfo(FALSE)
, m_nCommonEvent(FALSE)
, m_pConfig(nullptr)
, m_sConnectCenter(0)
, m_sConnectAuthorDB(0)
, m_sListenMaster(0)
, m_sListenExternal(0)
, m_FileLog(false)
{
}

INLINE CAuthorServer::~CAuthorServer(void)
{
}

INLINE CAuthorServer::CAuthorServer(const CAuthorServer&)
: m_nStatus(STATUSS_NONE)
, m_nCenterLink(STATUSL_NONE)
, m_nAuthorDBLink(STATUSL_NONE)
, m_nServerAck(TRUE)
, m_nSyncInfo(FALSE)
, m_nCommonEvent(FALSE)
, m_pConfig(nullptr)
, m_sConnectCenter(0)
, m_sConnectAuthorDB(0)
, m_sListenMaster(0)
, m_sListenExternal(0)
, m_FileLog(false)
{
}

INLINE CAuthorServer& CAuthorServer::operator=(const CAuthorServer&)
{
    return (*this);
}

INLINE bool CAuthorServer::OnTcpRecv(size_t, PTCP_PARAM)
{
    return false;
}

INLINE bool CAuthorServer::OnTcpSend(UInt, Socket)
{
    return true;
}

INLINE bool CAuthorServer::OnUdpRecv(size_t, PUDP_PARAM)
{
    return false;
}

INLINE bool CAuthorServer::OnUdpSend(UInt, Socket)
{
    return true;
}

INLINE Socket_t CAuthorServer::GetSocket(UInt uType)
{
    Socket_t sSocket = 0;
    switch (uType)
    {
    case PAKT_CENTER:
        {
            sSocket = m_sConnectCenter;
        }
        break;
    case PAKT_AUTHORDB:
        {
            sSocket = m_sConnectAuthorDB;
        }
        break;
    case PAKT_AUTHOR:
        {
            sSocket = m_sListenExternal;
        }
        break;
    case PAKT_MASTER:
        {
            sSocket = m_sListenMaster;
        }
        break;
    default:
        {
        }
    }
    return sSocket;
}

INLINE PSERVER_INFO CAuthorServer::GetServerInfo(UInt uType)
{
    if (uType == PAKT_AUTHOR)
    {
        return &m_ServerInfo;
    }
    else if (uType == PAKT_MASTER)
    {
        return &m_MasterInfo;
    }
    return nullptr;
}

INLINE PSVR_COMMON_MAP CAuthorServer::GetServerMap(UInt uType)
{
    if (uType == PAKT_MASTER)
    {
        return (PSVR_COMMON_MAP)&m_Master;
    }
    return nullptr;
}

INLINE PRESULT_CHAIN CAuthorServer::GetServerSort(UInt uType)
{
    if (uType == PAKT_MASTER)
    {
        return &m_SortMaster;
    }
    else if (uType == PAKT_MASTER_UPDATE)
    {
        return &m_SortUpdate;
    }
    return nullptr;
}

INLINE CServerConfig& CAuthorServer::GetConfig(void)
{
    return (*m_pConfig);
}

INLINE CFileLog& CAuthorServer::GetFileLog(void)
{
    return m_FileLog;
}

INLINE CEventHandlerPtr& CAuthorServer::GetMgrHandler(void)
{
    return m_MgrHandler;
}

INLINE CNetworkPtr& CAuthorServer::GetNetworkPtr(void)
{
    return m_NetworkPtr;
}

#endif // __AUTHOR_SERVER_IMP_H__
